package com.limiterframework.webaop;


import com.limiterframework.config.ServiceLimier;
import com.limiterframework.core.DoFlowLimiter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * web 请求拦截器，拦截加了ServiceLimier注解的请求，进行应用限流
 *
 */
@Configuration
public class LimiterInterceptor extends WebMvcConfigurerAdapter{
    private Logger logger = LoggerFactory.getLogger(LimiterInterceptor.class);
    @Autowired
    private JedisPool jedisPool;

    /**
     * aop拦截器，拦截请求，进行应用限流
     * @param registry
     */
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptorAdapter() {
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                                     Object handler) throws Exception {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                Method method = handlerMethod.getMethod();
                ServiceLimier serviceLimier = method.getAnnotation(ServiceLimier.class);

                if (serviceLimier != null) {
                    int limit = serviceLimier.limit();
                    int timeout = serviceLimier.timeout();
                    Jedis jedis = jedisPool.getResource();
                    String token = DoFlowLimiter.enAbleToAccess(jedis, method.getName(), limit, timeout);
                    if (token == null) {
                        response.sendError(500);
                        return false;
                    }
                    logger.debug("--获取分布式锁：token -> {}", token);
                    jedis.close();
                }
                return true;
            }
        }).addPathPatterns("/*");
    }
}
